#include "OriBodySendRelayHandler.h"
#include "AfterOriSendDispatcher.h"

using namespace log4cplus;

Logger OriBodySendRelayHandler::log=GetLogger(LOG4CPLUS_TEXT("OriBodySendRelayHandler"));

ITransHandler::ExecuteResultCode OriBodySendRelayHandler::Execute(ClientContext &client,OVERLAPPED *ovl)
{
	unsigned int clienSequenceNo=client.SequenceNo();
	LOG4CPLUS_DEBUG_FMT(log,LOG4CPLUS_TEXT("[Client%d]Start to relay client send."),clienSequenceNo);
	DWORD sendCount=-1;
	DWORD flags;
	BOOL result=::WSAGetOverlappedResult(client.SrcSock(),client.OVL(),&sendCount,true,&flags);
	int errCode=::WSAGetLastError();
	if(result)
	{
		long long &transIndex=client.TranslatedFileIndex();
		transIndex+=sendCount;
		LOG4CPLUS_DEBUG_FMT(log,LOG4CPLUS_TEXT("[Client%d]Send %d bytes data."),clienSequenceNo,sendCount);
		if(sendCount<client.WeakRefBuffer()->len)
		{
			LOG4CPLUS_DEBUG_FMT(log,LOG4CPLUS_TEXT("[Client%d]Send data not complete,resend."),clienSequenceNo);
			client.WeakRefBuffer()->buf+=sendCount;
			client.WeakRefBuffer()->len-=sendCount;
			::ZeroMemory(client.OVL(),sizeof(OVERLAPPED));
			int sendResult=::WSASend(client.SrcSock(),client.WeakRefBuffer(),1,NULL,0,client.OVL(),NULL);
			errCode=::WSAGetLastError();
			if(sendResult!=0&&errCode!=WSA_IO_PENDING)
			{
				LOG4CPLUS_ERROR_FMT(log,LOG4CPLUS_TEXT("[Client%d]Resend data failed,error code:%d."),clienSequenceNo,errCode);
				return ITransHandler::ExecuteFatalError;
			}
		}
		else
		{
			LOG4CPLUS_DEBUG_FMT(log,LOG4CPLUS_TEXT("[Client%d]Send data complete,rereceive(send body index:%d)."),clienSequenceNo,transIndex);
			delete client.SetCurrentHandler(GetNextHandler());
			::ZeroMemory(client.OVL(),sizeof(OVERLAPPED));
			DWORD flags=0;
			int recvResult=::WSARecv(client.DestSock(),client.Buffer(),1,NULL,&flags,client.OVL(),NULL);
			errCode=::WSAGetLastError();
			if(recvResult!=0&&errCode!=WSA_IO_PENDING)
			{
				LOG4CPLUS_ERROR_FMT(log,LOG4CPLUS_TEXT("[Client%d]Receive data failed,error code:%d."),clienSequenceNo,errCode);
				return ITransHandler::ExecuteFatalError;
			}
		}
	}
	else
	{
		LOG4CPLUS_ERROR_FMT(log,LOG4CPLUS_TEXT("[Client%d]Client send data failed,error code:%d."),clienSequenceNo,errCode);
		return ITransHandler::ExecuteFatalError;
	}
	return ITransHandler::ExecuteOK;
}

ITransHandler* OriBodySendRelayHandler::GetNextHandler()
{
	return new AfterOriSendDispatcher();
}